package com.photoeditor.demo.ui.widget.image;

import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.widget.ImageView;

import com.android.gpuimage.GPUImage;
import com.android.gpuimage.GPUImageFilter;
import com.android.gpuimage.IDynamicFilter;
import com.photoeditor.R;
import com.photoeditor.demo.db.FilterBean;
import com.photoeditor.demo.model.filter.ImageFilterTools;
import com.photoeditor.demo.ui.activity.edit.MediaEditBaseActivity;
import com.photoeditor.demo.util.BitmapUtils;

import java.lang.ref.WeakReference;
import java.util.LinkedHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 这个类用于加载和缓存Filter Icon
 * 进行了加锁 防止base bitmap 改变后缓存中还是错误的图片
 */
public class FilterIconManager {

    /**
     * 线程池
     */
    protected ExecutorService mThreadPool;

    private MediaEditBaseActivity mActivity;

    /**
     * 缓存图片的Map
     */
    private LinkedHashMap<String, Bitmap> mMap;

    private GPUImage mGPUImage;

    private Bitmap mBaseBitmap;

    private Object mLockObject = new Object();

    private final int mDefaultHeight;
    private final int mDefaultWidth;

    private Paint mPaint;
    private Rect mDrawRect;

    private static final int CACHE_SIZE = 100;

    private static final int MSG_END_RUNABLE = 100;
    private static final int MSG_CLEAR_MAP = 101;
    private static final int MSG_REFRESH_OR_RUN_THREAD = 102;

    private Handler mHandler = new Handler(Looper.getMainLooper()) {
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            if (msg.what == MSG_END_RUNABLE) {
                ImgBeanHolder holder = (ImgBeanHolder) msg.obj;
                FilterBean data = (FilterBean) holder.view.getTag();
                if (holder.bitmap != null && !holder.bitmap.isRecycled()
                        && holder.view != null && data != null && holder.bean != null
                        && holder.bean.getPackageName().equals(data.getPackageName())) {//确保是同一个 且一切正常
                    holder.view.setImageBitmap(holder.bitmap);
                    mMap.put(data.getPackageName(), holder.bitmap);
                }
            } else if (msg.what == MSG_CLEAR_MAP) {
                mMap.clear();
            } else if (msg.what == MSG_REFRESH_OR_RUN_THREAD) {
                ImgBeanHolder holder = (ImgBeanHolder) msg.obj;
                ImageView view = holder.view;
                FilterBean data = holder.bean;
                Bitmap bitmap = mMap.get(data.getPackageName());
                if (bitmap != null && !bitmap.isRecycled()) {
                    view.setImageBitmap(bitmap);
                } else {
                    mThreadPool.submit(new IconRunnable(view, data));
                }
            }
        }

        ;
    };

    private static final ThreadFactory sThreadFactory = new ThreadFactory() {
        private final AtomicInteger mCount = new AtomicInteger(1);

        public Thread newThread(Runnable r) {
            return new Thread(r, "FilterIconTask #" + mCount.getAndIncrement());
        }
    };

    public FilterIconManager(MediaEditBaseActivity activity) {
        mActivity = activity;
        mThreadPool = Executors.newSingleThreadExecutor(sThreadFactory);
        mMap = new LinkedHashMap<String, Bitmap>(CACHE_SIZE, 0.5f, true) {

            private static final long serialVersionUID = 1L;

            @Override
            protected boolean removeEldestEntry(Entry<String, Bitmap> eldest) {
                if (size() > CACHE_SIZE) {
                    return true;
                }
                return super.removeEldestEntry(eldest);
            }
        };

        /**
         * 注意不能太大  不然可能会溢出
         */
        mDefaultHeight = mActivity.getResources().getDimensionPixelSize(R.dimen.filter_height);
        mDefaultWidth = mDefaultHeight;
        mDrawRect = new Rect(0, 0, mDefaultWidth, mDefaultHeight);
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);

        mGPUImage = new GPUImage(activity, false);
    }

    /**
     * 设置默认的bitmap时要将缓存清除
     *
     * @param bitmap
     */
    public void setBaseBitmap(Bitmap bitmap) {
        synchronized (mLockObject) {
            if (bitmap == null) {
                mBaseBitmap = null;
            } else {
                mHandler.sendEmptyMessage(MSG_CLEAR_MAP);
                mBaseBitmap = Bitmap.createBitmap(mDefaultWidth, mDefaultHeight, Config.ARGB_8888);
                Rect bitmapRect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
                BitmapUtils.cropSetSquare(bitmapRect, 1f);
                Canvas c = new Canvas(mBaseBitmap);
                c.drawBitmap(bitmap, bitmapRect, mDrawRect, mPaint);
            }
        }
    }

    /**
     * 加载Icon
     *
     * @param view
     * @param data
     */
    public void loadIcon(ImageView view, FilterBean data) {
        if (data != null && view != null) {//排队执行
            Message msg = Message.obtain(mHandler, MSG_REFRESH_OR_RUN_THREAD);
            ImgBeanHolder bean = new ImgBeanHolder();
            bean.view = view;
            bean.bean = data;
            msg.obj = bean;
            mHandler.sendMessage(msg);
        }
    }

    public void onDestory() {
        try {
            mThreadPool.shutdownNow();
            mMap.clear();
            synchronized (mLockObject) {
                mBaseBitmap = null;
            }
        } catch (Throwable e) {
            e.printStackTrace();
        }
    }

    class IconRunnable implements Runnable {

        private final WeakReference<ImageView> mImageViewReference;
        private FilterBean mData;

        public IconRunnable(ImageView iv, FilterBean data) {
            mImageViewReference = new WeakReference<ImageView>(iv);
            mData = data;
        }

        @Override
        public void run() {
            if (mData != null) {
                ImageView imageview = mImageViewReference.get();
                FilterBean data = (FilterBean) imageview.getTag();
                synchronized (mLockObject) {
                    if (mBaseBitmap != null && imageview != null && data != null && mData != null
                            && data.getPackageName().equals(mData.getPackageName())) {
                        GPUImageFilter filter = ImageFilterTools.createFilterForType(mActivity, mData);
                        if (filter instanceof IDynamicFilter) {
                            IDynamicFilter dynamicFilter = (IDynamicFilter) filter;
                            dynamicFilter.setUpdateOn(false);
                        }
                        mGPUImage.setFilter(filter, false);
                        Bitmap bitmap = mGPUImage.getBitmapWithFilterApplied(mBaseBitmap);
                        Message msg = Message.obtain(mHandler, MSG_END_RUNABLE);
                        ImgBeanHolder bean = new ImgBeanHolder();
                        bean.bitmap = bitmap;
                        bean.view = imageview;
                        bean.bean = mData;
                        msg.obj = bean;
                        mHandler.sendMessage(msg);
                    }
                }
            }
        }
    }

    protected class ImgBeanHolder {
        Bitmap bitmap;
        ImageView view;
        FilterBean bean;
    }
}
